package com.example.annotation.apt.dto;

import com.example.annotation.apt.BaseProcessor;
import com.google.auto.service.AutoService;
import com.google.common.collect.Sets;
import com.squareup.javapoet.*;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;

import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import java.util.Set;


@AutoService(Processor.class)
public class GenDTOProcessor extends BaseProcessor<GenDTO> {
    public GenDTOProcessor() {
        super(GenDTO.class);
    }

    @Override
    protected void foreachClass(GenDTO genDTO, Element element, RoundEnvironment roundEnv) {
        String className = "Base" + element.getSimpleName().toString() + "DTO";

        Set<TypeAndName> typeAndNames = Sets.newHashSet();
        // 获取元素中字段信息
        Set<TypeAndName> fields = findFields(element, filterForIgnore(GenDTOIgnore.class));
        typeAndNames.addAll(fields);

        // 获取元素中的Getter信息
        Set<TypeAndName> getters = findGetter(element, filterForIgnore(GenDTOIgnore.class));
        typeAndNames.addAll(getters);

        // 生成Java类， 类名为className, 添加Data注解，并使用public、abstract关键字描述
        TypeSpec.Builder typeSpecBuilder = TypeSpec.classBuilder(className)
                .addAnnotation(Data.class)
                .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);

        // 生成构造函数
        MethodSpec.Builder cMethodSpecBuilder = MethodSpec.constructorBuilder()
                .addParameter(TypeName.get(element.asType()), "source")
                .addModifiers(Modifier.PROTECTED);

        for (TypeAndName typeAndName : typeAndNames) {
            // 声明BaseDomainDTO中的字段信息，Setter方法设置为private，Getter方法设置为public
            FieldSpec fieldSpec = FieldSpec.builder(typeAndName.getType(), typeAndName.getName(), Modifier.PRIVATE)
                    .addAnnotation(AnnotationSpec.builder(Setter.class)
                            .addMember("value", "$T.PRIVATE", AccessLevel.class)
                            .build())
                    .addAnnotation(AnnotationSpec.builder(Getter.class)
                            .addMember("value", "$T.PUBLIC", AccessLevel.class)
                            .build())
                    .build();
            typeSpecBuilder.addField(fieldSpec);

            String fieldName = typeAndName.getName().substring(0, 1).toUpperCase() + typeAndName.getName().substring(1, typeAndName.getName().length());

            // 构造函数中添加设置语句
            cMethodSpecBuilder.addStatement("this.set$L(source.get$L())", fieldName, fieldName);
        }

        // 将构造函数添加到类中
        typeSpecBuilder.addMethod(cMethodSpecBuilder.build());

        // 生成Java文件
        String pkgName = genDTO.pkgName();
        createJavaFile(typeSpecBuilder, pkgName);

    }
}
